﻿using Xejen.Communication.Configuration;
using Xejen.Communication.Endpoints;
using Xejen.Communication.Ftp.Abstract;
using Xejen.Communication.Ftp.Communicator;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Xejen.Communication.Ftp.Test
{
    public partial class MainForm : Form
    {
        private readonly IFtpCommunicator _communicator;
        private readonly HeartbeatConfig _heartbeatConfig;
        public MainForm(IFtpCommunicator communicator)
        {
            _communicator = communicator;
            _communicator.Config.JsonSerializerOptions.Converters.Add(new ExceptionConverter());

            _heartbeatConfig = communicator.Heartbeat.HeartbeatConfig;

            //以下3种方式均可以注册心跳检测逻辑
            //第1种：
            //communicator.Heartbeat.LocalHeartbeatCheck = () =>
            //{
            //    Debug.WriteLine($"本地心跳检测时间：{DateTime.Now.ToString()}");
            //    byte[] buffer = Guid.NewGuid().ToByteArray();
            //    var value = BitConverter.ToInt64(buffer, 0);

            //    return value % 2 == 1;
            //};
            //communicator.Heartbeat.RemoteHeartbeatCheck = () =>
            //{
            //    Debug.WriteLine($"远端心跳检测时间：{DateTime.Now.ToString()}");
            //    byte[] buffer = Guid.NewGuid().ToByteArray();
            //    var value = BitConverter.ToInt64(buffer, 0);

            //    return value % 2 == 0;
            //};
            //第2种
            //communicator.Heartbeat.RegisterHeartbeatChecker(new HeartbeatChecker());
            //第3种
            communicator.Heartbeat.RegisterHeartbeatChecker<HeartbeatConfig, HeartbeatChecker>();

            InitializeComponent();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            _communicator.Heartbeat.LocalAliveChanged += (object sender, AliveStatusEventArgs args) =>
            {
                Debug.WriteLine($"设备是否在线：{args.CurrentStatus}");

                Invoke((MethodInvoker)(() =>
                {
                    LocalAliveLabel.Text = args.CurrentStatus.ToString();
                }));
            };
            _communicator.Heartbeat.RemoteAliveChanged += (object sender, AliveStatusEventArgs args) =>
            {
                Debug.WriteLine($"远端是否在线：{args.CurrentStatus}");

                Invoke((MethodInvoker)(() =>
                {
                    RemoteAliveLabel.Text = args.CurrentStatus.ToString();
                }));
            };
        }

        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void button1_Click(object sender, EventArgs e)
        {
            var address = new FtpAddress
            {
                //上传之前，请确保FTP目录下有"大文件目录"这个文件夹，若没有，请手工创建或者用 对应的ftp命令创建
                Path = "大文件目录\\Xejen.Communication.2023.12.29.1.nupkg",
            };

            var result = await _communicator.UploadFileAsync(address, @"E:\Xejen.Communication.2023.12.29.1.nupkg");
            ShowResult(result);
        }

        /// <summary>
        /// 上传大文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button8_Click(object sender, EventArgs e)
        {
            Task.Run(async () =>
            {
                var address = new FtpAddress
                {
                    //上传之前，请确保FTP目录下有"大文件目录"这个文件夹，若没有，请手工创建或者用 对应的ftp命令创建
                    Path = "大文件目录\\halcon-20.11.1.0-windows.exe",
                };

                //报告进度
                ProgressTextBox.Text = string.Empty;
                var progress = new Progress<IProgressData>(ReportProgress);
                var result = await _communicator.UploadFileAsync(address, @"E:\halcon-20.11.1.0-windows.exe", progress);

                //不需要进度
                //var result = await _communicator.UploadFileAsync(address, @"E:\halcon-20.11.1.0-windows.exe");
                ShowResult(result);
            });
        }

        /// <summary>
        /// 附加文件内容
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void button6_Click(object sender, EventArgs e)
        {
            //将本地某个文件的内容附加到服务器上存在的文件中去。内容将加在服务器上文件的内容末尾处
            var result = await _communicator.AppendFileAsync(new FtpAddress
            {
                Path = "大文件目录/问题11.txt",//服务器上存在的文件 
            }, @"E:\1.txt");
            ShowResult(result);
        }

        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void button5_Click(object sender, EventArgs e)
        {
            var address = new FtpAddress
            {
                Path = "问题.txt",//服务器上存在的文件 
            };

            ProgressTextBox.Text = string.Empty;
            var progress = new Progress<IProgressData>(ReportProgress);

            var result = await _communicator.DownloadFileAsync(address, @"E:\dowload.txt", progress);
            ShowResult(result);
        }

        private readonly object _lockObject = new object();
        private readonly TimeSpan UpdateInterval = TimeSpan.FromMilliseconds(100);
        private DateTime _lastUpdate = DateTime.MinValue;

        void ReportProgress(IProgressData progress)
        {
            lock (_lockObject)
            {
                DateTime now = DateTime.Now;
                if (now - _lastUpdate >= UpdateInterval)
                {
                    _lastUpdate = now;

                    Debug.WriteLine($"{progress.Message}: 已处理字节数[ {progress.BytesRead} ], 总字节数[ {progress.TotalBytes} ]");

                    BeginInvoke((MethodInvoker)(() =>
                    {
                        ProgressTextBox.Text = $"{progress.Message}: 已处理字节数[ {progress.BytesRead} ], 总字节数[ {progress.TotalBytes} ]{Environment.NewLine}" + ProgressTextBox.Text;
                    }));
                }
            }
        }

        /// <summary>
        /// 下载大文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void button2_Click(object sender, EventArgs e)
        {
            var address = new FtpAddress
            {
                Path = "微软常用运行库合集 2022.01.23.exe",//服务器上存在的文件 
            };

            var progress = new Progress<IProgressData>(ReportProgress);

            var result = await _communicator.DownloadFileAsync(address, @"E:\dowload.exe", progress);
            ShowResult(result);
        }

        /// <summary>
        /// 创建目录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void button4_Click(object sender, EventArgs e)
        {
            var address = new FtpAddress
            {
                Path = "中国/福建/连城",
            };

            var result = await _communicator.MakeDirectoryAsync(address);
            ShowResult(result);
        }

        /// <summary>
        /// 创建多级目录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void button9_Click(object sender, EventArgs e)
        {
            var address = new FtpAddress
            {
                Path = "\\大文件目录\\小目录/啦啦队目录/中国队/李宁队\\",
            };

            var result = await _communicator.MakeDirectoryAsync(address);
            ShowResult(result);

            var address2 = new FtpAddress
            {
                Path = "\\测试目录\\小目录1/",
            };

            var result2 = await _communicator.MakeDirectoryAsync(address2);
            ShowResult(result2);
        }

        private async void button3_Click(object sender, EventArgs e)
        {
            var address = new FtpAddress
            {
                Path = "大文件目录/问题.txt",//服务器上存在的文件 
            };

            var result1 = await _communicator.RenameFileAsync(address, "mazhiyuan.txt");
            ShowResult(result1);

            address = new FtpAddress
            {
                Path = "大文件目录/mazhiyuan.txt",//服务器上存在的文件 
            };

            var result2 = await _communicator.RenameFileAsync(address, "小问题.txt");
            ShowResult(result2);
        }

        private async void button7_Click(object sender, EventArgs e)
        {
            var address = new FtpAddress
            {
                Path = "新建文本文档.txt",//服务器上存在的文件 
                                    //Path = "大文件目录/新建文本文档.txt",//服务器上不存在的文件 
            };

            var result = await _communicator.DeleteFileAsync(address);
            ShowResult(result);
        }

        private async void button16_Click(object sender, EventArgs e)
        {
            var address = new FtpAddress
            {
                Path = "问题.txt",//服务器上存在的文件 
                                //Path = "大文件目录/问题.txt",//服务器上不存在的文件 
            };

            var result = await _communicator.GetDateTimestampAsync(address);
            var date = result.ReturnData;
            ShowResult(result);
        }

        private async void button15_Click(object sender, EventArgs e)
        {
            var address = new FtpAddress
            {
                //Path = "问题.txt",//服务器上存在的文件 
                Path = "大文件目录/问题.txt",//服务器上不存在的文件 
            };

            var result = await _communicator.GetFileSizeAsync(address);
            ShowResult(result);
        }

        private async void button11_Click(object sender, EventArgs e)
        {
            var address = new FtpAddress
            {
                Path = "新建文件夹",//服务器上存在的文件 
            };

            var result = await _communicator.RemoveDirectoryAsync(address);
            ShowResult(result);
        }

        private async void button10_Click(object sender, EventArgs e)
        {
            var address = new FtpAddress
            {
                Path = "中国",//服务器上存在的文件 
                            //Path = "中国/安徽",//服务器上不存在的文件 
            };

            var result = await _communicator.UploadFileWithUniqueNameAsync(address, @"E:\问题.txt");
            ShowResult(result);
        }

        private async void button14_Click(object sender, EventArgs e)
        {
            var address = new FtpAddress
            {
                Path = "中国",//服务器上存在的文件 
                            //Path = "中国/日本",//服务器上不存在的文件 
            };

            var result = await _communicator.ListDirectoryAsync(address);
            ShowResult(result);
        }

        private async void button13_Click(object sender, EventArgs e)
        {
            var address = new FtpAddress
            {
                //Path = "中国",//服务器上存在的文件 
                Path = "中国/美国",//服务器上不存在的文件 
            };

            var result = await _communicator.ListDirectoryDetailsAsync(address);
            ShowResult(result);
        }

        private async void button12_Click(object sender, EventArgs e)
        {
            var address = new FtpAddress
            {
                //Path = "中国",//服务器上存在的文件 
                Path = "//中国/美国",//服务器上不存在的文件 
            };

            var result = await _communicator.PrintWorkingDirectoryAsync(address);
            ShowResult(result);
        }

        private void ShowResult(FtpResponse result)
        {
            Debug.WriteLine(JsonExtensions.ToJson(result, _communicator.Config.JsonSerializerOptions));
        }
        private void ShowResult<T>(FtpResponse<T> result)
        {
            Debug.WriteLine(JsonExtensions.ToJson(result, _communicator.Config.JsonSerializerOptions));
        }

        /// <summary>
        /// 修改心跳周期
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ChangeHeartbeatIntervalButton_Click(object sender, EventArgs e)
        {
            //想测试自动重启心跳定时器的。不好整
            //_heartbeatConfig.Interval = 500;
        }
    }
}
